import { observe } from "./observer/index";
import { proxy, isObject } from "./util/index";
import Watcher from "./observer/watcher";
export function initState(vm) {
  const opts = vm.$options;
  if (opts.props) {
    initProps(vm);
  }
  if (opts.methods) {
    initMethod(vm);
  }
  if (opts.data) {
    initData(vm);
  }
  if (opts.computed) {
    initComputed(vm, opts.computed);
  }
  if (opts.watch) {
    initWatch(vm, opts.watch);
  }
}
function initProps(vm) {}
function initMethod(vm) {}

function initData(vm) {
  // 数据初始化
  let data = vm.$options.data; // 获取用户传递进来的data
  data = typeof data === "function" ? data.call(vm) : data;

  // 让使用者可以获取到data数据
  vm._data = data;
  // console.log("initData", data);

  // 可在页面上更方便取值，vm._data.name --> vm.name
  for (let key in data) {
    proxy(vm, "_data", key);
  }

  // 响应式数据，数据变化驱动视图变化
  // Object.defineProperty 给属性增加get set方法
  observe(data);
}
// computed 的实现
function initComputed(vm, computed) {
  // _computedWatchers 存放所有计算属性对应的watcher
  const watchers = vm._computedWatchers = {};
  for(let key in computed) { //计算属性可能会有多个值
    const userDef = computed[key]; // 获取用户定义的计算属性函数
    const getter = typeof userDef === 'function' ? userDef : userDef.get;
    // 通过获取到getter函数，创建watcher
    watchers[key] = new Watcher(vm, getter, ()=>{}, {lazy: true}); //计算属性中的options中设置lazy

    // 计算属性直接通过vm取值
    defineComputed(vm, key, userDef)
  } 
}
// 定义属性描述器
const sharedPropertyDefinition ={
  enumerable: true,
  configurable: true,
  get:()=>{}
}
function defineComputed(target, key, userDef) {
  if(typeof userDef === 'function'){
    sharedPropertyDefinition.get = createComputedGetter(key);
  }else{
    sharedPropertyDefinition.get = createComputedGetter(key);
    sharedPropertyDefinition.set = userDef.set || (()=>{})
  }
  Object.defineProperty(target, key, sharedPropertyDefinition)
}

function createComputedGetter(key){ //根据key【allname】，创建getter
  return function(){
    // console.log("123", this);
    let watcher = this._computedWatchers[key];
    if(watcher.dirty){ // 如果 dirty 为真，则使用缓存数据
      watcher.evaluate();
    }
    if(Dep.target){
      watcher.depend()
    }
    return watcher.value;
  }
}

// watch 是通过watcher实现
function initWatch(vm, watch) {
  // console.log(vm, watch);
  for(let key in watch) {
    const handler = watch[key];
    if(Array.isArray(handler)) {
      for(let i = 0; i < handler.length; i++) {
        createWatcher(vm, key, handler[i])
      }
    }else{
      createWatcher(vm, key, handler);
    }
  }
}

function createWatcher(vm, key, handler, options) {
  if(isObject(handler)){
    options = handler;
    handler = handler.handler;
  }
  if(typeof handler === 'string'){ //如果是字符串，说明handler被写到methods中
    handler = vm.$options.methods[handler]
  }
  // watch的重点实现,基于$watch实现
  return vm.$watch(key, handler, options);
  // console.log(handler, options);
}

export function stateMixin(Vue){
  // 定义的用户watcher中，exprOrFn为字符串类型
  Vue.prototype.$watch = function(exprOrFn, callback, options={}){
    const vm = this;
    // 用户watcher
    options.user = true;
    new Watcher(vm, exprOrFn, callback, options);
  }
}